package com.eralink.unionuhfreader.util;

import androidx.core.util.Pools;

public class CachePool {
    private final Pools.SynchronizedPool<CacheNode> poolFor64Bytes = new Pools.SynchronizedPool<>(1000);
    private final Pools.SynchronizedPool<CacheNode> poolFor128Bytes = new Pools.SynchronizedPool<>(500);
    private final Pools.SynchronizedPool<CacheNode> poolFor256Bytes = new Pools.SynchronizedPool<>(200);
    private final Pools.SynchronizedPool<CacheNode> poolFor512Bytes = new Pools.SynchronizedPool<>(100);
    private final Pools.SynchronizedPool<CacheNode> poolFor1024Bytes = new Pools.SynchronizedPool<>(50);

    private CachePool() {
        for (int i = 0; i < 500; ++i) {
            poolFor64Bytes.release(new CacheNode(new byte[64]));
        }
    }

    private static class SingletonClassInstance {
        private static final CachePool instance = new CachePool();
    }

    public static CachePool getInstance() {
        return SingletonClassInstance.instance;
    }

    public CacheNode obtain(int size) {
        if (0 > size || 1024 < size) {
            return null;
        }

        if (0 == size) {
            return new CacheNode(new byte[0]);
        }

        CacheNode node;
        int bufferCapacity = 64;
        if (size <= 64) {
            node = poolFor64Bytes.acquire();
        } else if (size <= 128) {
            bufferCapacity = 128;
            node = poolFor128Bytes.acquire();
        } else if (size <= 256) {
            bufferCapacity = 256;
            node = poolFor256Bytes.acquire();
        } else /* if (size <= 1024) */ {
            bufferCapacity = 1024;
            node = poolFor1024Bytes.acquire();
        }

        if (node == null) {
            node = new CacheNode(new byte[bufferCapacity]);
        }

        return node;
    }

    public boolean release(CacheNode node) {
        if (null == node || null == node.getBuffer() || 0 == node.getBuffer().length) {
            return true;
        }

        if (64 == node.getBuffer().length) {
            return poolFor64Bytes.release(node);
        } else if (128 == node.getBuffer().length) {
            return poolFor128Bytes.release(node);
        } else if (256 == node.getBuffer().length) {
            return poolFor256Bytes.release(node);
        } else if (512 == node.getBuffer().length) {
            return poolFor512Bytes.release(node);
        } else if (1024 == node.getBuffer().length) {
            return poolFor1024Bytes.release(node);
        }

        return true;
    }
}
